package pers.cz.postgirl.adapter;

import javassist.*;

import pers.cz.postgirl.core.AssistEventListener;
import pers.cz.postgirl.core.EnhanceModel;
import pers.cz.postgirl.core.Event;
import pers.cz.postgirl.core.EventListener;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;

/**
 * @program: postgirl-client
 * @description: 抽象
 * @author: Cheng Zhi
 * @create: 2023-05-23 12:47
 **/
public abstract class AbstractTransformer implements ClassFileTransformer {

    /**
     * 待增强类描述
     */
    public EnhanceModel enhanceModel;

    private EventListener eventListener = new AssistEventListener();

    public AbstractTransformer() {
        // 装载增强信息
        loadEnhanceModel();
    }

    /**
     * 修改class
     * @param loader
     * @param className
     * @param classBeingRedefined
     * @param protectionDomain
     * @param classfileBuffer
     * @return
     * @throws IllegalClassFormatException
     */
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

        if (enhanceModel == null) {
            return null;
        }

        className = className.replace("/", ".");

        if (className.equals(enhanceModel.getClassPattern())) {
            // 找到增强类
            try {
                ClassPool classPool = new ClassPool(true);
                classPool.insertClassPath(new LoaderClassPath(loader));
                CtClass ctClass = classPool.get(enhanceModel.getClassPattern());
                for (Event event : enhanceModel.getEvent()) {
                    eventListener.onEvent(event , ctClass);
                }
                return ctClass.toBytecode();
            } catch (NotFoundException e) {
                e.printStackTrace();
            } catch (CannotCompileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }

        }
        return null;
    }

    public abstract void loadEnhanceModel();

}
